"""
Case Type   : 操作系统类-文件系统故障
Case Name   : gs_ctl启停时，备机注入故障系统文件句柄耗尽
Create At   : 2021/7/23
Owner       : @peilinqian
Description :
    1、备节点注入60s句柄耗尽故障
    2、备节点上执行gs_ctl stop 故障清理后gs_ctl stop
    3、备节点注入60s句柄耗尽故障
    4、备节点上执行gs_ctl start 故障清理后gs_ctl start
Expect      :
    1、备节点注入60s句柄耗尽故障成功
    2、备节点上执行gs_ctl stop失败，故障清理后gs_ctl stop成功
    3、备节点注入60s句柄耗尽故障成功
    4、备节点上执行gs_ctl start失败，故障清理后gs_ctl start成功
History     :
    Modified by @peilinqian 2021/8/23: 优化故障清理
    Modified by @peilinqian 2021/12/9: 优化故障清理后重启数据库
    Modified by @peilinqian 2024/2/21: 优化用例删除不必要步骤
    Modified by @peilinqian 2024/7/9： 优化用例，增加清理等待时间;备机session提前建连操作，防止直接执行连接异常
    Modified by @peilinqian 2024/8/12： 优化用例，数据库启动以备机启动
"""
import os
import time
import unittest

from testcase.utils.ComThread import ComThread
from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node


class ReliabilityFileSystem(unittest.TestCase):
    nodes = ("PrimaryDbUser", "Standby1DbUser", "Standby2DbUser")

    @RestartDbCluster(*nodes)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.pri_sh = CommonSH(self.nodes[0])
        self.sta_1_sh = CommonSH(self.nodes[1])
        self.sta1_root = Node(node="Standby1Root")
        self.constant = Constant()
        self.com = Common()
        self.inject_time = 60
        self.inject_cmd = f"rfile_deplenish (timeout) values " \
                          f"({self.inject_time})"
        self.check_cmd = "df -h"

    def test_main(self):
        self.log.info("----备节点查询集群状态----")
        self.sta_1_sh.getDbClusterStatus()

        step_txt = '----step1:备节点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.sta1_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()
        time.sleep(5)
        check_msg = self.sta1_root.sh(self.check_cmd).result()
        self.log.info(check_msg)

        step_txt = '----step2:备节点上执行gs_ctl stop; expect:失败----'
        self.log.info(step_txt)
        result = self.sta_1_sh.executeGsctl("stop", "", get_detail=True)
        self.assertIn(self.constant.TOO_MANYY_FILE_MSG, result,
                      "执行失败" + step_txt)
        self.assertNotIn(self.constant.GS_CTL_STOP_SUCCESS_MSG, result,
                         "执行失败" + step_txt)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break

        step_txt = '----step2:故障清理后，备节点上执行gs_ctl stop; expect:成功----'
        self.log.info(step_txt)
        result = self.sta_1_sh.executeGsctl("stop", "", get_detail=True)
        self.assertNotIn(self.constant.TOO_MANYY_FILE_MSG, result,
                         "执行失败" + step_txt)
        self.assertTrue(self.constant.no_process_msg in result.lower() or
                        self.constant.GS_CTL_STOP_SUCCESS_MSG in result,
                        "执行失败" + step_txt)

        step_txt = '----step3:备节点注入60s句柄耗尽故障; expect:成功----'
        self.log.info(step_txt)
        session = ComThread(self.com.cfe_inject,
                            args=(self.sta1_root,
                                  self.inject_cmd))
        session.setDaemon(True)
        session.start()
        self.start_time = time.time()

        step_txt = '----step4:备节点上执行gs_ctl start; expect:失败----'
        self.log.info(step_txt)
        result = self.sta_1_sh.startDbInstance('standby')
        self.assertNotIn(self.constant.RESTART_SUCCESS_MSG, result)

        self.log.info("-----注入故障结果-----")
        session.join(60)
        result = session.get_result()
        self.log.info(result)
        self.assertIn(self.constant.SUCCESS_CFE_FULL_FILENUM_MSG, result,
                      "执行失败" + step_txt)
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break

        step_txt = '----step4:故障清理后，备节点上再次执行gs_ctl start; expect:成功----'
        self.log.info(step_txt)
        result = self.sta_1_sh.startDbInstance('standby')
        self.log.info(result)
        self.assertIn(self.constant.RESTART_SUCCESS_MSG, result)

    def tearDown(self):
        self.log.info("----this is tearDown----")
        text = "-----确认故障清理干净-----"
        self.log.info(text)
        while True:
            time.sleep(5)
            check_msg = self.sta1_root.sh(self.check_cmd).result()
            self.log.info(check_msg)
            if self.constant.TOO_MANYY_FILE_MSG not in check_msg:
                break
            end_time = time.time()
            if end_time - self.start_time > self.inject_time * 10:
                break
        step_txt = '----集群状态异常时，恢复环境----'
        self.log.info(step_txt)
        status = self.pri_sh.getDbClusterStatus("status")
        if not status:
            self.result = self.pri_sh.startDbCluster()
            self.final_status = self.pri_sh.getDbClusterStatus("status")
        self.log.info(f'-----{os.path.basename(__file__)} end-----')
        if not status:
            self.assertIn(self.constant.START_SUCCESS_MSG, self.result,
                          "执行失败" + step_txt)
            self.assertTrue(self.final_status, "执行失败" + step_txt)
